package com.cn.udpDemo;

import com.cn.udpDemo.message.Message;
import com.cn.udpDemo.message.MessageType;
import com.cn.udpDemo.message.MessageUtils;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class UDPClient extends Thread {

    // 心跳使用周期性任务来发送
    //
    public  void  run () {
        DatagramChannel channel =  null ;
        Selector selector =  null ;
        SocketAddress sa = null;
        int udpPort=5000;
        ByteBuffer byteBuffer = null;
        Map<String,InetSocketAddress> mapAddr = new HashMap<>();
        try  {
            channel = DatagramChannel.open () ;
            channel.configureBlocking ( false ) ;
            sa =  new InetSocketAddress( "localhost" ,udpPort) ;
            selector = Selector.open () ;
            channel.register (selector, SelectionKey.OP_READ ) ;

            Message message=Message.build(MessageType.HEARTBEAT);
            byteBuffer=MessageUtils.toByteBuffer(message);
            int count=channel.send(byteBuffer,sa);
        }  catch  ( Exception e ) {
            e.printStackTrace () ;
        }

//        ByteBuffer byteBuffer = ByteBuffer.allocate (100) ;
        while  ( true ) {
            try  {
                int  eventsCount = selector.select () ;
                if  ( eventsCount >  0 ) {
                    Set selectedKeys = selector.selectedKeys () ;
                    Iterator iterator = selectedKeys.iterator () ;
                    while  ( iterator.hasNext ()) {
                        SelectionKey sk =  ( SelectionKey )  iterator.next () ;
                        iterator.remove () ;
                        if  ( sk.isReadable ()) {
                            //在这里datagramChannel与channel实际是同一个对象
                            DatagramChannel datagramChannel =  ( DatagramChannel )  sk.channel () ;
                            byteBuffer.clear();
                            ByteBuffer buffer = ByteBuffer.allocate (1024) ;
                            SocketAddress isa=datagramChannel.receive(buffer);
//                            buffer.flip();
                            Message message = MessageUtils.fromByteBuffer(buffer);
                            if (message.getType()==MessageType.SERVERLIST){
                                MessageUtils.toObject(message.getData());
                            }else if (message.getType()==MessageType.HEARTBEAT){
                                // 测试：通过将收到的ByteBuffer首先通过缺省的编码解码成CharBuffer 再输出
//                                System.out.println ( Charset.defaultCharset().decode (byteBuffer ) .toString ()) ;
                                System.out.println("收到来自："+isa.toString()+" 的心跳"+ message.getData().toString());
//                                byte [] bytes = {0x07};
//                                message.setData(bytes);
                                Thread.sleep(3000);
                                ByteBuffer buff=MessageUtils.toByteBuffer(message);
                                int count=datagramChannel.send(buff,isa) ;
                            }

                        }
                    }
                }
            }  catch  ( Exception e ) {
                e.printStackTrace () ;
            }
        }

    }

    public static void main (String[] args) {
        new UDPClient().start();
    }
}
